#pragma once
#include<iostream>
#include<string>
#include<fstream>
#include<boost/algorithm/string.hpp>
#include<mutex>
#include<unordered_map>
#include"log.hpp"

//利用软连接方式找到我们的头文件，不止要include还需要dict两个目录，而且再include里面的cppjieba里面我们需要拷贝一份cppjieba/deps/limonp目录文件-------很重要
#include"cppjieba/Jieba.hpp"


//工具头文件

namespace ns_util
{
    class FileUtil
    {
    public:
        static bool ReadFile(const std::string& file_path,std::string* file)
        {
            //使用c++文件流打开我们的文件
            //std::ifstream in(file_path,std::ios::in);//也可以这样写
            std::ifstream in(file_path);//默认第二个参数为std::ios::in

            //打开文件失败就返回
            if(!in.is_open())
            {
                std::cerr << "open file" << file_path << " error !!" << std::endl;
                return false;
            }

            std::string line;
            while(std::getline(in,line))//getline的返回值是istream&，明显是个对象，但是istream类内重载了istream强制类型转换成为bool，因此这里可以判断。
            {
                *file += line;
            }
            return true;
        }
    };


    //关于字符串的工具
    class StringUtil
    {
    public:
        //利用boost库来进行字符串的切割
        static void StringSplit(const std::string& target,std::vector<std::string>* result,const std::string& sep)
        {
            boost::split(*result,target,boost::is_any_of(sep),boost::token_compress_on);
        }
    };


    const char* const DICT_PATH = "./dict/jieba.dict.utf8";
    const char* const HMM_PATH = "./dict/hmm_model.utf8";
    const char* const USER_DICT_PATH = "./dict/user.dict.utf8";
    const char* const IDF_PATH = "./dict/idf.utf8";
    const char* const STOP_WORD_PATH = "./dict/stop_words.utf8";

    class JieBaUtil
    {
    public:
        ~JieBaUtil()
        {}
        static JieBaUtil* GetInstance()
        {
            if(instance == nullptr)
            {
                mtx.lock();
                if(instance == nullptr)
                {
                    instance = new JieBaUtil;
                    instance->InitJieBaUtil();
                }
                mtx.unlock();
            }
            return instance;
        }
    private:
        JieBaUtil():jieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH)
        {}
        JieBaUtil(const JieBaUtil&) = delete;
        JieBaUtil& operator=(const JieBaUtil&) = delete;
    private:
    //创建一个静态成员对象，供所有使用，不用重复创建jieba对象
        //static cppjieba::Jieba jieba;
        cppjieba::Jieba jieba;
        static JieBaUtil* instance;
        std::unordered_map<std::string,bool> stop_words;
        static std::mutex mtx;

        //初始化暂停词列表
        void InitJieBaUtil()
        {
            std::ifstream in(STOP_WORD_PATH);
            if(!in.is_open())
            {
                LOG(FATAL,"open stop words file error");
                return;
            }

            std::string line;
            while(std::getline(in,line))
            {
                stop_words.insert({line,true});
            }

            in.close();
        }
    public:

        //静态成员函数的帮手，方便获取成员便利
        void CutStringHelper(const std::string& src,std::vector<std::string>* result)
        {
            jieba.CutForSearch(src,*result);
            for(auto iter = result->begin();iter != result->end();)
            {
                auto it = stop_words.find(*iter);
                if(it != stop_words.end())
                {
                    iter = result->erase(iter);
                }
                else
                {
                    iter++;
                }
            }
        }
        //我们的jieba分词工具，直接调用即可,对象是我们的静态成员对象不用自己创建
        static void CutString(const std::string& src,std::vector<std::string>* result)
        {
            //jieba.CutForSearch(src,*result);
            GetInstance()->CutStringHelper(src,result);
        }
    };
    JieBaUtil* JieBaUtil::instance = nullptr;
    std::mutex JieBaUtil::mtx;
    //cppjieba::Jieba JieBaUtil::jieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH);
}